﻿using Autodesk.AutoCAD.Geometry;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Interop;

namespace DonetArxLib
{
    class PointData : IComparable<PointData>
    {
        public int index;

        public double X;
        public double Y;
        public double Z;

        public int CompareTo(PointData other)
        {
            if (this.X.CompareTo(other.X) != 0)
                return this.X.CompareTo(other.X);
            else if (this.Y.CompareTo(other.Y) != 0)
                return this.Y.CompareTo(other.Y);
            else
                return this.Z.CompareTo(other.Z);
        }

        public bool isEqul(PointData other)
        {
            if (Math.Sqrt((this.X - other.X) * (this.X - other.X) +
                (this.Y - other.Y) * (this.Y - other.Y) +
                (this.Z - other.Z) * (this.Z - other.Z)) < 0.00000001)
                return true;

            return false;
        }
    }


    internal class MeshGenerator
    {
        private List<PointData> _vertices = new List<PointData>();
        private List<int> _triangles = new List<int>();
        private List<PointData> _uniqueVertices = new List<PointData>();

        public void AddTriangle(Point3d p1, Point3d p2, Point3d p3)
        {
            AddPoint(p1);
            AddPoint(p2);
            AddPoint(p3);
        }

        private void AddPoint(Point3d pt)
        {
            _vertices.Add(new PointData { index = _vertices.Count, X = pt.X, Y = pt.Y, Z = pt.Z });
            _triangles.Add(0);
        }

        public void Generate()
        {
            _vertices.Sort();

            int newIndexPosition = 0;
            _triangles[_vertices[0].index] = 0;
            _uniqueVertices.Add(_vertices[0]);

            for (int i = 1; i < _vertices.Count; i++)
            {
                if (!_vertices[i].isEqul(_vertices[i - 1]))
                {
                    newIndexPosition++;
                    _uniqueVertices.Add(_vertices[i]);
                }                  

                _triangles[_vertices[i].index] = newIndexPosition;
            }
        }

        public void WriteFile(string filename)
        {
            MemoryStream ms = new MemoryStream(); //new StreamWriter(filename + ".vert", false, Encoding.UTF8);
            PointData originPoint = _uniqueVertices[0];

            for (int i = 0; i < _uniqueVertices.Count; i++)
            {
                var pt = _uniqueVertices[i];
                WriteDouble(ms, pt.X - originPoint.X);
                WriteDouble(ms, pt.Y - originPoint.Y);
                WriteDouble(ms, pt.Z - originPoint.Z);
            }
            File.WriteAllBytes(filename + ".vert", ms.GetBuffer());
            ms.Close();
            ms.Dispose();


            StreamWriter sw = new StreamWriter(filename + ".index", false, Encoding.UTF8);
            for (int i = 0; i < _triangles.Count; i += 3)
            {
                sw.WriteLine($"{_triangles[i]},{_triangles[i + 1]},{_triangles[i + 2]}");
            }

            sw.Flush();
            sw.Close();
        }

        private void WriteDouble(MemoryStream ms, double value)
        {
            var bytes = BitConverter.GetBytes(value);
            ms.Write(bytes, 0, bytes.Length);
        }

        public int GetTriangleCount()
        {
            return _triangles.Count;
        }

        public int GetVertexCount()
        {
            return _vertices.Count;
        }
    }
}
